I Ubuntu, I am learning about cmake and make, and just trying a simple example. I have two directories: src and build. In src, I have two files: main.cpp, with just a simple hello world example, and CMakeLists.txt, with the following text:
add_executable(test main.cpp)
target_link_libraries(test blas)
Here, blas is just some arbitrary library that I've found at /usr/lib/libblas.so. My main.cpp file does not actually use it, but I am just testing things out...
Now, if I enter the build directory, and run cmake ../src, then a makefile is generated in build. The contents of that makefile is pasted below.
What I am puzzled about, is why there is no mention of the blas library at all? Shouldn't cmake be adding a line such as -lblas?
Thanks :)
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The program to use to edit the cache.
CMAKE_EDIT_COMMAND = /usr/bin/cmake-gui
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/ejohns/Projects/Test2/src
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/ejohns/Projects/Test2/build
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target edit_cache
edit_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
/usr/bin/cmake-gui -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/ejohns/Projects/Test2/build/CMakeFiles /home/ejohns/Projects/Test2/build/CMakeFiles/progress.marks
$(MAKE) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /home/ejohns/Projects/Test2/build/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named test
# Build rule for target.
test: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 test
.PHONY : test
# fast build rule for target.
test/fast:
$(MAKE) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/build
.PHONY : test/fast
main.o: main.cpp.o
.PHONY : main.o
# target to build an object file
main.cpp.o:
$(MAKE) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/main.cpp.o
.PHONY : main.cpp.o
main.i: main.cpp.i
.PHONY : main.i
# target to preprocess a source file
main.cpp.i:
$(MAKE) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/main.cpp.i
.PHONY : main.cpp.i
main.s: main.cpp.s
.PHONY : main.s
# target to generate assembly for a file
main.cpp.s:
$(MAKE) -f CMakeFiles/test.dir/build.make CMakeFiles/test.dir/main.cpp.s
.PHONY : main.cpp.s
# Help Target
help:
#echo "The following are some of the valid targets for this Makefile:"
#echo "... all (the default if no target is provided)"
#echo "... clean"
#echo "... depend"
#echo "... edit_cache"
#echo "... rebuild_cache"
#echo "... test"
#echo "... main.o"
#echo "... main.i"
#echo "... main.s"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system
CMake uses a 3-level hierarchy of makefiles. The line you're looking for will be either in CMakeFiles/Makefile2 or in build.make somewhere under CMakeFiles (and probably a test directoty as well).
Related
I have a makefile (gnu make) working under linux, but when porting it to windows it does not work. The goal of the makefile is to make all the *.cpp file that reside in different subdirectories and compile them into *.obj files in a single BUILD_DIR.
Between linux and windows I only adjusted the SOURCES variable, the linux line is shown but commented. When I check all the names and directories they show the same (relative paths in their perspective notation) and what I expect.
The "error message" I get on windows is: make: *** No rule to make target 'DEM.cpp', needed by 'DEM.obj'. Stop.
In debug mode it says: File 'DEM.cpp' does not exist. (which it obviously does)
On linux it finds the file via the VPATH, in debug mode it says: No need to remake target 'DEM.cpp'; using VPATH name './Code/DEM.cpp'.
The subdirectory structure in both linux and windows is the same and the makefile is run from the same location.
Question: What is going wrong here, I have the feeling it has something to do with VPATH being handled differently on windows but I am not certain.
My makefile is:
# MAKEFILE
# Some makefile settings
SHELL = /bin/sh #Make sure the shell is the standard shell
.SUFFIXES: #Clear al implicit suffixes
.SUFFIXES: .cpp .obj #Set used suffixes
# Variable Declaration
CXX := g++
BUILD_DIR = .\bin\Release
PROGRAM_NAME := DEM.exe
#SOURCES := $(shell find . -name '*.cpp') #All *.cpp files with directory (LINUX style)
SOURCES := $(shell FORFILES /S /M *.cpp /C "CMD /C ECHO #relpath") #All *.cpp files with directory
NAMES := $(notdir $(basename $(SOURCES))) #Get all files names of the *.cpp files without extensions
OBJECTS := $(addsuffix .obj, $(NAMES)) #Get the to be generate *.o files without directory
SRC_DIRS := $(dir $(SOURCES)) #All the directory in which the sources are found
VPATH := $(SRC_DIRS) $(BUILD_DIR)
.PHONY: all
all: build #Standard entry point, run release
#echo "BUILD DONE"
.PHONY: build
build: $(PROGRAM_NAME)
#echo "BUILD DONE"
$(PROGRAM_NAME): $(OBJECTS)
#echo "Link executable"
$(CXX) -o $(BUILD_DIR)/$(PROGRAM_NAME) $(addprefix $(BUILD_DIR)/,$(OBJECTS))
$(OBJECTS): %.obj: %.cpp
#echo "Compile into object code: $<"
${CXX} $(CXXFLAGS) -c $< -o $(BUILD_DIR)/$# #Compiles object code and places it in the $(BUILD_DIR)
Update 1: Based on the comment of some programmer dude, I ran it with -p, and got the following interesting result:
# Not a target:
DEM.cpp:
# Implicit rule search has been done.
# File does not exist.
# File has not been updated.
# Not a target:
World.cpp:
# Implicit rule search has not been done.
# Modification time never checked.
# File has not been updated.
# Lot more targets below
It seems only to not find DEM.cpp but it finds everything else.
DEM.cpp resides in C:\Users\dklomp\Documents\Programming\C++ Source\DEM\DEM\Code, but should resolve to .\Code\
Most other files reside in subdirectories in Code.
But stdafx.cpp also resides in .\Code\ and there is no problem finding it.
Can it be a name clash with the directory name DEM being similar to DEM.cpp
Update 2: For information and closure.
I had already check the VPATH by reading the variable by printing it this seemed to give the correct information. However if i read it with #(info $(VPATH)) it seemet empty:
#echo "VPATH print variable: "
#echo "$(VPATH)"
#echo "VPATH print info: "
$(info VPATH)
gave:
"VPATH print variable: "
"./Code/InputOutput/ ./Code/InputOutput/ ./Code/InputOutput/
./Code/InputOutput/ ./Code/ ./Code/ ./Code/Models/ ./Code/Models/
./Code/Forces/ ./Code/Forces/ ./Code/Forces/ ./Code/Forces/ ./Code/Forces/
./Code/Forces/ ./Code/Forces/ ./Code/Forces/ ./Code/Forces/ ./Code/Tools/
./Code/Tools/ ./Code/Tools/ ./Code/Tools/ ./Code/Solvers/ ./Code/Solvers/
./Code/Solvers/ ./Code/World/ ./Code/World/ ./Code/World/ ./Code/World/
./Code/World/ ./Code/Interactions/ ./Code/Interactions/ ./Code/Interactions/
./Code/Interactions/ ./Code/Interactions/ ./Code/Interactions/
bin\Release"
"VPATH print info: "
Indeed with a lot of repetitions (will use the sort suggestion of hardcoreHenry) but it seemed oke. However the VPATH info is empty for some reason.
However implementing the proposed solution by code_fodder and removing all the inline code comments works. The inline code comments on the variable declaration do not seem to matter, those in the rules section do for windows, linux seems to handle inline code comments fine everywhere.
As usually thanks for the help and suggestions.
I tested this in a path that had spaces before the current location (e.g. like d:\path with spaces\myfolder\sub_folder1\sub_folder2\).
I think there is some issue with the FORFILES syntax/output - at least I could not get it to work. As soon as I used the more generic rwildcard from second answer from here it started to work quite well. Then I added rules to create/clean your output folder.
Also I removed any inline comments, since I am not 100% sure they are valid because they leave space characters everywhere and makefile is not very tolerant of that... I.E. make-sure you don't leave any trailing white space on any lines.
Also - this all assumes its gnu-make and not nmake
# MAKEFILE
# Some makefile settings
SHELL = /bin/sh
.SUFFIXES:
.SUFFIXES: .cpp .obj
# Variable Declaration
CXX := g++
BUILD_DIR = .\bin\Release
PROGRAM_NAME := DEM.exe
# Define a recursive wild card function that is portable.
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
#SOURCES := $(shell FORFILES /S /M *.cpp /C "CMD /C ECHO #relpath")
SOURCES := $(call rwildcard, ./, *.cpp)
$(info SOURCES: $(SOURCES))
NAMES := $(notdir $(basename $(SOURCES)))
OBJECTS := $(addsuffix .obj, $(NAMES))
SRC_DIRS := $(dir $(SOURCES))
VPATH := $(SRC_DIRS) $(BUILD_DIR)
.PHONY: all
all: create_dirs build
#echo "BUILD DONE"
# Has an order dependency on create_dirs to ensure that happens first, and so
# it works with parallel build (e.g. `make -j4`)
.PHONY: build
build: $(PROGRAM_NAME) | create_dirs
#echo "BUILD DONE"
$(PROGRAM_NAME): $(OBJECTS)
#echo "Link executable"
$(CXX) -o $(BUILD_DIR)/$(PROGRAM_NAME) $(addprefix $(BUILD_DIR)/,$(OBJECTS))
$(OBJECTS): %.obj: %.cpp
#echo "Compile into object code: $<"
${CXX} $(CXXFLAGS) -c $< -o $(BUILD_DIR)/$#
.PHONY: create_dirs
create_dirs:
#echo "creating dirs"
mkdir -p $(BUILD_DIR)
.PHONY: clean
clean:
#echo "cleaning"
rm -rf $(BUILD_DIR)
I'm currently learning CMake, which I understand to be a build file generator, and I wanted to see the exact command that CMake was running to compile and link my C++ files. For example, if I'm working with a single file main.cpp and I were to compile it with gcc, I would run gcc -o main main.cpp. How would I see the C++ command that CMake is running? I tried make VERBOSE=1 but that only reveals CMake-related commands instead of C++ compiler commands.
// main.cpp
#include <iostream>
int main()
{
std::cout << "Hello world" << std::endl;
}
//CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
project(example LANGUAGES CXX)
add_executable(main main.cpp)
This creates a Makefile with the following contents:
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.14
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/local/Cellar/cmake/3.14.5/bin/cmake
# The command to remove a file.
RM = /usr/local/Cellar/cmake/3.14.5/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /Users/.../Desktop/cpp
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /Users/.../Desktop/cpp/build
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target rebuild_cache
rebuild_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/local/Cellar/cmake/3.14.5/bin/cmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# Special rule for the target edit_cache
edit_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
/usr/local/Cellar/cmake/3.14.5/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /Users/.../Desktop/cpp/build/CMakeFiles /Users/.../Desktop/cpp/build/CMakeFiles/progress.marks
$(MAKE) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /Users/.../Desktop/cpp/build/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named main
# Build rule for target.
main: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 main
.PHONY : main
# fast build rule for target.
main/fast:
$(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/build
.PHONY : main/fast
main.o: main.cpp.o
.PHONY : main.o
# target to build an object file
main.cpp.o:
$(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.cpp.o
.PHONY : main.cpp.o
main.i: main.cpp.i
.PHONY : main.i
# target to preprocess a source file
main.cpp.i:
$(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.cpp.i
.PHONY : main.cpp.i
main.s: main.cpp.s
.PHONY : main.s
# target to generate assembly for a file
main.cpp.s:
$(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.cpp.s
.PHONY : main.cpp.s
# Help Target
help:
#echo "The following are some of the valid targets for this Makefile:"
#echo "... all (the default if no target is provided)"
#echo "... clean"
#echo "... depend"
#echo "... rebuild_cache"
#echo "... edit_cache"
#echo "... main"
#echo "... main.o"
#echo "... main.i"
#echo "... main.s"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system
make VERBOSE=1 returns:
/usr/local/Cellar/cmake/3.14.5/bin/cmake -S/Users/.../Desktop/cpp -B/Users/.../Desktop/cpp/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/local/Cellar/cmake/3.14.5/bin/cmake -E cmake_progress_start /Users/.../Desktop/cpp/build/CMakeFiles /Users/.../Desktop/cpp/build/CMakeFiles/progress.marks
/Applications/Xcode.app/Contents/Developer/usr/bin/make -f CMakeFiles/Makefile2 all
/Applications/Xcode.app/Contents/Developer/usr/bin/make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/depend
cd /Users/.../Desktop/cpp/build && /usr/local/Cellar/cmake/3.14.5/bin/cmake -E cmake_depends "Unix Makefiles" /Users/.../Desktop/cpp /Users/.../Desktop/cpp /Users/.../Desktop/cpp/build /Users/.../Desktop/cpp/build /Users/.../Desktop/cpp/build/CMakeFiles/main.dir/DependInfo.cmake --color=
Dependee "/Users/.../Desktop/cpp/build/CMakeFiles/main.dir/DependInfo.cmake" is newer than depender "/Users/.../Desktop/cpp/build/CMakeFiles/main.dir/depend.internal".
Dependee "/Users/.../Desktop/cpp/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/Users/.../Desktop/cpp/build/CMakeFiles/main.dir/depend.internal".
Scanning dependencies of target main
/Applications/Xcode.app/Contents/Developer/usr/bin/make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/build
[ 50%] Building CXX object CMakeFiles/main.dir/main.cpp.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -o CMakeFiles/main.dir/main.cpp.o -c /Users/.../Desktop/cpp/main.cpp
[100%] Linking CXX executable main
/usr/local/Cellar/cmake/3.14.5/bin/cmake -E cmake_link_script CMakeFiles/main.dir/link.txt --verbose=1
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/main.dir/main.cpp.o -o main
[100%] Built target main
/usr/local/Cellar/cmake/3.14.5/bin/cmake -E cmake_progress_start /Users/.../Desktop/cpp/build/CMakeFiles 0
I have a project in c++ that I want to be reasonably portable, and can be compiled by issuing a single "make" command. I currently use boost headers for certain operations, but now need "filesystem" from boost, which requires compilation.
I know there is a way to compile boost using the included shell script, but that takes FOREVER. I am curious of a way to selectively compile boost libraries, as specified from a makefile and include them in the linking process.
My current general idea is:
Have a makefile variable of the boost libraries wanted to be compiled and included.
Compile those libraries (before any dependent projects) from a boost distribution folder, AND output compiled binaries to a specific folder in the makefile project (eg: a "lib" folder)
I understand how to have these files included in the project by using:
-Llib
What is the best way to do this, as well as choose where the boost output from compilation is? Should the files be .a or .o files? (or no extension?)
This is the wilder older brother of the prior answer's manual makefile. Given a path to the BOOST distro, BOOST_DISTRO, it finds the relevant source files for the target libs specified in TARGET_BOOST_LIBS, compiles them into $(WORK_FOLDER)/<lib>/, and archives the resulting objects into $(DEST_FOLDER)/libboost_<lib>.a.
BOOST_DISTRO=.
DEST_FOLDER=libs
WORK_FOLDER=build
TARGET_BOOST_LIBS=\
system \
filesystem \
serialization
.PHONY: all
all: $(foreach lib,$(TARGET_BOOST_LIBS),$(DEST_FOLDER)/libboost_$(lib).a )
$(DEST_FOLDER):
mkdir -p $(DEST_FOLDER)
$(WORK_FOLDER):
mkdir -p $(WORK_FOLDER)
#####
# helper for building the .o files in WORK_FOLDER
#####
define MAKE_BOOST_LIB_COMPILE_RULES
$(foreach cppfile,$(shell ls $(BOOST_DISTRO)/boost/libs/$(1)/src/*.cpp),$(WORK_FOLDER)/$(1)/$(notdir $(cppfile:.cpp=.o)): $(cppfile) | $(WORK_FOLDER)/$(1)
$(CXX) $(CXXFLAGS) -D BOOST_ALL_NO_LIB \
-I$(BOOST_DISTRO)/boost \
-c $$^ \
-o $$#
)
endef
#####
# define the build rules based on the files we find in the subfolders of
# the boost distro that correspond to our library names
#####
define BUILD_BOOST_LIB
$(WORK_FOLDER)/$(1): | $(WORK_FOLDER)
mkdir -p $$#
$(call MAKE_BOOST_LIB_COMPILE_RULES,$(1))
$(DEST_FOLDER)/libboost_$(1).a: $(foreach cppfile,$(notdir $(shell ls $(BOOST_DISTRO)/boost/libs/$(1)/src/*.cpp)),$(WORK_FOLDER)/$(1)/$(cppfile:.cpp=.o)) | $(DEST_FOLDER)
ar r $$# $$^
ranlib $$#
endef
#####
# dynamically generate the build rules from the list of libs
#####
$(foreach lib,$(TARGET_BOOST_LIBS),$(eval $(call BUILD_BOOST_LIB,$(lib))))
.PHONY: clean
clean:
-rm -rf $(WORK_FOLDER)
-rm -rf $(DEST_FOLDER)
Testing with my ancient BOOST (#define BOOST_VERSION 105500), this builds the listed libs, and a dummy test program successfully compiles and calls boost::filesystem::absolute().
Using lockcmpxchg8b's answer, I was able to adapt it to my needs.
It was a little tricky to get makefiles to work right when recursively called, but I was able to get it to work.
SHELL = /bin/sh
# This makefile expects multiple arguments to be passed:
#
# Use the pattern: make var_name="var_value" when invoking this makefile
#
# BOOST_VER (the version suffix )
# BOOST_LIBS_TO_BUILD (space delimited list of boost libraries to build)
# BOOST_LIB_DIR (the output lib dir for the boost libraries)
# BOOSTDIR (the base directory to build from)
#
# Compile Info
CXX = g++
CXXFLAGS = -Wall -std=c++11
WORK_FOLDER = obj_boost$(BOOST_VER)
.PHONY: all
all: $(foreach lib,$(BOOST_LIBS_TO_BUILD),$(BOOST_LIB_DIR)/libboost_$(lib).a )
$(BOOST_LIB_DIR):
#mkdir -p $(BOOST_LIB_DIR)
$(WORK_FOLDER):
#mkdir -p $(WORK_FOLDER)
#####
# helper for building the .o files in WORK_FOLDER
#####
define MAKE_BOOST_LIB_COMPILE_RULES
$(foreach cppfile,$(shell ls $(BOOSTDIR)/libs/$(1)/src/*.cpp),$(WORK_FOLDER)/$(1)/$(notdir $(cppfile:.cpp=.o)): $(cppfile) | $(WORK_FOLDER)/$(1)
$(CXX) $(CXXFLAGS) -D BOOST_ALL_NO_LIB \
-I$(BOOSTDIR) \
-c $$^ \
-o $$#
)
endef
#####
# define the build rules based on the files we find in the subfolders of
# the boost distro that correspond to our library names
#####
define BUILD_BOOST_LIB
$(WORK_FOLDER)/$(1): | $(WORK_FOLDER)
#mkdir -p $$#
$(call MAKE_BOOST_LIB_COMPILE_RULES,$(1))
$(BOOST_LIB_DIR)/libboost_$(1).a: $(foreach cppfile,$(notdir $(shell ls $(BOOSTDIR)/libs/$(1)/src/*.cpp)),$(WORK_FOLDER)/$(1)/$(cppfile:.cpp=.o)) | $(BOOST_LIB_DIR)
#ar r $$# $$^
#ranlib $$#
endef
#####
# dynamically generate the build rules from the list of libs
#####
$(foreach lib,$(BOOST_LIBS_TO_BUILD),$(eval $(call BUILD_BOOST_LIB,$(lib))))
.PHONY: clean
clean:
#rm -rf $(WORK_FOLDER)
#rm -rf $(BOOST_LIB_DIR)/*
#echo "---- Done Cleaning Boost Libs ----"
To call this makefile, I call it from another makefile using the following:
# Boost
BOOST_VER= _1_65_1
BOOST_LIBS_TO_BUILD = filesystem timer chrono
#relative to this file
BOOST_LIB_DIR = shared/lib_boost$(BOOST_VER)
#relative to this file
BOOSTDIR = shared/boost$(BOOST_VER)
#Subdirectories
DIRECTORIES = $(sort $(dir $(wildcard */makefile)))
.PHONY: build
build: dependencies
#$(foreach dir,$(DIRECTORIES),$(MAKE) -C $(dir);)
dependencies:
#echo "---- Build Dependencies ----"
#$(MAKE) -C shared -f build_boost_libs.mk BOOST_LIBS_TO_BUILD="$(BOOST_LIBS_TO_BUILD)" BOOST_LIB_DIR="../$(BOOST_LIB_DIR)" BOOSTDIR="../$(BOOSTDIR)" BOOST_VER="$(BOOST_VER)"
The pattern to CORRECTLY invoke a recursive make is:
$(MAKE) -C subdir_of_makefile -f makefile_name.mk
The use of $(MAKE) is the proper way to invoke make (as per documentation -- it ensures the same make command is used as the top-most make) and to correctly change the running directory, you need to use the -C argument (otherwise the directory context of any sub-make is the top-most parent makefile in the call stack). The -f option specifies a makefile that is anything but a default name for a makefile. This takes into account the -C option when looking for the named makefile.
I also found out that passing "arguments" to a makefile is a bit tricky, and is usually done with export and unexport, but the problem with those is due to ONLY the LAST "status" of a variable to be exported is used for the ENTIRE makefile. You can't export a variable, call a sub-make, then unexport. It would be unexported for the entire makefile run (as the last "status" of the variable was to be unexported despite it being called after the sub-make). Variable "status" is computed/parsed before the makefile executes.
Thanks for the help! I appreciate it. I'll also be releasing this makefile in an open-source project in the future (I'll credit your username as helping with that)
I want to compile jsoncpp with -fPIC through cmake.
In the website for jsoncpp, it is explaining the way normally to compile like below.
mkdir -p build/debug
cd build/debug
cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_STATIC=ON -DJSONCPP_LIB_BUILD_SHARED=OFF -G "Unix Makefiles" ../..
make
How can i compile with -fPIC flag in this step?
---------------------------------------------------------Edit-----------------------------------------------------------
I assume i have to put some line in makefile for -fPIC.
So i add the content of makefile by cmake.
how can i change this makefile for -fPIC flag?
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E remove -f
# The program to use to edit the cache.
CMAKE_EDIT_COMMAND = /usr/bin/cmake-gui
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/kim/jsoncpp-pre-C-11
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/kim/jsoncpp-pre-C-11/build/debug
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target edit_cache
edit_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
/usr/bin/cmake-gui -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target install
install: preinstall
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
/usr/bin/cmake -P cmake_install.cmake
.PHONY : install
# Special rule for the target install
install/fast: preinstall/fast
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
/usr/bin/cmake -P cmake_install.cmake
.PHONY : install/fast
# Special rule for the target install/local
install/local: preinstall
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
/usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local
# Special rule for the target install/local
install/local/fast: install/local
.PHONY : install/local/fast
# Special rule for the target install/strip
install/strip: preinstall
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
/usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip
# Special rule for the target install/strip
install/strip/fast: install/strip
.PHONY : install/strip/fast
# Special rule for the target list_install_components
list_install_components:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
.PHONY : list_install_components
# Special rule for the target list_install_components
list_install_components/fast: list_install_components
.PHONY : list_install_components/fast
# Special rule for the target rebuild_cache
rebuild_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# Special rule for the target test
test:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..."
/usr/bin/ctest --force-new-ctest-process $(ARGS)
.PHONY : test
# Special rule for the target test
test/fast: test
.PHONY : test/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/kim/jsoncpp-pre-C-11/build/debug/CMakeFiles /home/kim/jsoncpp-pre-C-11/build/debug/CMakeFiles/progress.marks
$(MAKE) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /home/kim/jsoncpp-pre-C-11/build/debug/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named jsoncpp_lib
# Build rule for target.
jsoncpp_lib: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 jsoncpp_lib
.PHONY : jsoncpp_lib
# fast build rule for target.
jsoncpp_lib/fast:
$(MAKE) -f src/lib_json/CMakeFiles/jsoncpp_lib.dir/build.make src/lib_json/CMakeFiles/jsoncpp_lib.dir/build
.PHONY : jsoncpp_lib/fast
#=============================================================================
# Target rules for targets named jsoncpp_check
# Build rule for target.
jsoncpp_check: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 jsoncpp_check
.PHONY : jsoncpp_check
# fast build rule for target.
jsoncpp_check/fast:
$(MAKE) -f src/jsontestrunner/CMakeFiles/jsoncpp_check.dir/build.make src/jsontestrunner/CMakeFiles/jsoncpp_check.dir/build
.PHONY : jsoncpp_check/fast
#=============================================================================
# Target rules for targets named jsoncpp_readerwriter_tests
# Build rule for target.
jsoncpp_readerwriter_tests: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 jsoncpp_readerwriter_tests
.PHONY : jsoncpp_readerwriter_tests
# fast build rule for target.
jsoncpp_readerwriter_tests/fast:
$(MAKE) -f src/jsontestrunner/CMakeFiles/jsoncpp_readerwriter_tests.dir/build.make src/jsontestrunner/CMakeFiles/jsoncpp_readerwriter_tests.dir/build
.PHONY : jsoncpp_readerwriter_tests/fast
#=============================================================================
# Target rules for targets named jsontestrunner_exe
# Build rule for target.
jsontestrunner_exe: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 jsontestrunner_exe
.PHONY : jsontestrunner_exe
# fast build rule for target.
jsontestrunner_exe/fast:
$(MAKE) -f src/jsontestrunner/CMakeFiles/jsontestrunner_exe.dir/build.make src/jsontestrunner/CMakeFiles/jsontestrunner_exe.dir/build
.PHONY : jsontestrunner_exe/fast
#=============================================================================
# Target rules for targets named jsoncpp_test
# Build rule for target.
jsoncpp_test: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 jsoncpp_test
.PHONY : jsoncpp_test
# fast build rule for target.
jsoncpp_test/fast:
$(MAKE) -f src/test_lib_json/CMakeFiles/jsoncpp_test.dir/build.make src/test_lib_json/CMakeFiles/jsoncpp_test.dir/build
.PHONY : jsoncpp_test/fast
# Help Target
help:
#echo "The following are some of the valid targets for this Makefile:"
#echo "... all (the default if no target is provided)"
#echo "... clean"
#echo "... depend"
#echo "... edit_cache"
#echo "... install"
#echo "... install/local"
#echo "... install/strip"
#echo "... list_install_components"
#echo "... rebuild_cache"
#echo "... test"
#echo "... jsoncpp_lib"
#echo "... jsoncpp_check"
#echo "... jsoncpp_readerwriter_tests"
#echo "... jsontestrunner_exe"
#echo "... jsoncpp_test"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system
You have to change the CMAKE_CXX_FLAGS and the CMAKE_C_FLAGS variable. You can do that via the ccmake or cmake-gui (you'll have to toggle advanced) or you can provide it as you were doing:
cmake -DCMAKE_CXX_FLAGS=-fPIC -DCMAKE_C_FLAGS=-fPIC -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_STATIC=ON -DJSONCPP_LIB_BUILD_SHARED=OFF -G "Unix Makefiles" ../..
Don't bother changing the Makefile, as it would be overwritten the next time you ran cmake.
In CMake 2.8.9 you can set the POSITION_INDEPENDENT_CODE property
on a target to make all following targets position independent. Or you can set the global variable within the CMakeLists.txt
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
or
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
after making a breakthrough with my earlier MiniGW problem i have come across another. This is very diffrent from my understanding. from what i see everything compiles ok and i dont have a good enough understanding of cmake to know what the problem is.
here is the Error log
||=== Build: Icarus in Icarus (compiler: GNU GCC Compiler) ===|
CMakeFiles\Makefile2|60|recipe for target 'CMakeFiles/Icarus.dir/all' failed|
CMakeFiles\Makefile2|72|recipe for target 'CMakeFiles/Icarus.dir/rule' failed|
D:\Projects\SVN\Icarus\build\Makefile|110|recipe for target 'Icarus' failed|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|
Here is the line in the makefile it points to
# Build rule for target.
Icarus: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 Icarus
.PHONY : Icarus
And here is the first section it points to in makefile2
CMakeFiles/Icarus.dir/all:
$(MAKE) -f CMakeFiles/Icarus.dir/build.make CMakeFiles/Icarus.dir/depend
$(MAKE) -f CMakeFiles/Icarus.dir/build.make CMakeFiles/Icarus.dir/build
$(CMAKE_COMMAND) -E cmake_progress_report D:/Projects/SVN/Icarus/build/CMakeFiles
#echo "Built target Icarus"
.PHONY : CMakeFiles/Icarus.dir/all
And finally here is the final section
# Build rule for subdir invocation for target.
CMakeFiles/Icarus.dir/rule: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start D:/Projects/SVN/Icarus/build/CMakeFiles 31
$(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/Icarus.dir/all
$(CMAKE_COMMAND) -E cmake_progress_start D:/Projects/SVN/Icarus/build/CMakeFiles 0
.PHONY : CMakeFiles/Icarus.dir/rule
hopefully this is enough information to fix the error.
Edit information from about the error
Running command: c:/MinGW/bin/make.exe -f "D:/Projects/SVN/Icarus/build/Makefile" VERBOSE=1 Icarus
"c:/Program Files (x86)/CMake/bin/cmake.exe" -HD:/Projects/SVN/Icarus -BD:/Projects/SVN/Icarus/build --check-build-system CMakeFiles/Makefile.cmake 0
c:/MinGW/bin/make.exe -f CMakeFiles/Makefile2 Icarus
make.exe[1]: Entering directory 'D:/Projects/SVN/Icarus/build'
"c:/Program Files (x86)/CMake/bin/cmake.exe" -HD:/Projects/SVN/Icarus -BD:/Projects/SVN/Icarus/build --check-build-system CMakeFiles/Makefile.cmake 0
"c:/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_progress_start D:/Projects/SVN/Icarus/build/CMakeFiles 31
c:/MinGW/bin/make.exe -f CMakeFiles/Makefile2 CMakeFiles/Icarus.dir/all
make.exe[2]: Entering directory 'D:/Projects/SVN/Icarus/build'
c:/MinGW/bin/make.exe -f CMakeFiles/Icarus.dir/build.make CMakeFiles/Icarus.dir/depend
make.exe[3]: Entering directory 'D:/Projects/SVN/Icarus/build'
"C:\Program Files (x86)\CMake\bin\cmake.exe" -E cmake_depends "MinGW Makefiles" D:\Projects\SVN\Icarus D:\Projects\SVN\Icarus D:\Projects\SVN\Icarus\build D:\Projects\SVN\Icarus\build D:\Projects\SVN\Icarus\build\CMakeFiles\Icarus.dir\DependInfo.cmake --color=
make.exe[3]: Leaving directory 'D:/Projects/SVN/Icarus/build'