I want to write a generic Makefile for OpenSCAD 3D designs.
Those designs consist of a .scad file and a corresponding .json file, which contains parameter sets.
The Make file should create a folder named output and call OpenSCAD for each parameter set found in the .json file.
So far I've come up with this:
# Parametric OpenSCAD design file
OPENSCAD_FILE = hsw_parametric_hook.scad
# JSON file containing parameter sets
PARAMETER_SETS_FILE = hsw_parametric_hook.json
# Output directory for generated STL files
OUTPUT_DIR = output
# Function to extract parameter set names from the JSON file
get_parameter_set_names = $(shell jq -r '.parameterSets | keys[]' $(PARAMETER_SETS_FILE))
# Function to construct the STL filename for a given parameter set
stl_filename = $(OUTPUT_DIR)/$(basename $(OPENSCAD_FILE))-$(1).stl
.PHONY: all clean
all: $(OUTPUT_DIR) $(foreach set,$(call get_parameter_set_names),$(call stl_filename,$(set)))
$(OUTPUT_DIR):
mkdir -p $@
$(call stl_filename,%): $(OPENSCAD_FILE) $(PARAMETER_SETS_FILE)
openscad -o $@ $(OPENSCAD_FILE) -p $(PARAMETER_SETS_FILE) -P '$(subst .stl,,$(subst $(subst .scad,,$(OPENSCAD_FILE))-,,$(@F)))'
clean:
rm -f $(OUTPUT_DIR)/*.stl
The problem with this is, that it can't handle parameter set names containing a space character. I guess quoting is missing or messed up somehow.
Could anyone tell me how I could fix this?
The current directory could also contain more than one set of .scad and .json files. I would like the Makefile to be able to handle this as well and ideally not have those filenames hard-coded, as they are right now.
Any suggestions?
Update 2024-03-29:
I've incorporated a suggestion from @JohnBollinger to add a missing dependency, though it is unrelated to the issue.
I also created a more complete example, as requested by @MadScientist:
cylinder.scad
diameter = 10;
heigh = 5;
cylinder(d=diameter, h=height);
cylinder.json
{
"parameterSets": {
"Wide cylinder": {
"diameter": "20",
"height": "5"
}
},
"fileFormatVersion": "1"
}
Makefile
# Parametric OpenSCAD design file
OPENSCAD_FILE = cylinder.scad
# JSON file containing parameter sets
PARAMETER_SETS_FILE = cylinder.json
# Output directory for generated STL files
OUTPUT_DIR = output
# Function to extract parameter set names from the JSON file
get_parameter_set_names = $(shell jq -r '.parameterSets | keys[]' $(PARAMETER_SETS_FILE))
# Function to construct the STL filename for a given parameter set
stl_filename = $(OUTPUT_DIR)/$(basename $(OPENSCAD_FILE))-$(1).stl
.PHONY: all clean
all: $(OUTPUT_DIR) $(foreach set,$(call get_parameter_set_names),$(call stl_filename,$(set)))
$(OUTPUT_DIR):
mkdir -p $@
$(call stl_filename,%): $(OPENSCAD_FILE) $(PARAMETER_SETS_FILE) $(OUTPUT_DIR)
openscad -o $@ $(OPENSCAD_FILE) -p $(PARAMETER_SETS_FILE) -P '$(subst .stl,,$(subst $(subst .scad,,$(OPENSCAD_FILE))-,,$(@F)))'
clean:
rm -f $(OUTPUT_DIR)/*.stl
Running make now, creates the following output:
openscad -o output/cylinder-Wide.stl cylinder.scad -p cylinder.json -P 'Wide'
Geometries in cache: 1
Geometry cache size in bytes: 2456
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Total rendering time: 0:00:00.000
Top level object is a 3D object:
Facets: 18
openscad -o output/cylinder-cylinder.stl cylinder.scad -p cylinder.json -P 'cylinder'
Geometries in cache: 1
Geometry cache size in bytes: 2456
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Total rendering time: 0:00:00.000
Top level object is a 3D object:
Facets: 18