I am trying out to use CMake to cross-compile a program, but it failed with this message:
/bin/sh: 1: Syntax error: ";;" unexpected The program compiles perfectly with a raw Makefile
Here is my CMake file:
cmake_minimum_required(VERSION 3.9) project(my_target LANGUAGES CUDA CXX C) include(CheckLanguage) check_language(CUDA) # STD if (NOT DEFINED CMAKE_CUDA_STANDARD) set(CMAKE_CUDA_STANDARD 11) set(CMAKE_CUDA_STANDARD_REQUIRED ON) endif() find_package(Poco REQUIRED Foundation Util) # Flags set ( CMAKE_C_STANDARD 11 ) set( CMAKE_CXX_STANDARD 11 ) set( CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -c -Wall -fopenmp ) set( CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -c -Wall -fopenmp ) set( CMAKE_CUDA_FLAGS ${CMAKE_NVCC_FLAGS} --ccbin $(CMAKE_CXX_COMPILER) -O2 -gencode -std=c++11 -dc -Werror deprecated-declarations ) # Compile Objects file(GLOB_RECURSE src_c src/*.c ) file(GLOB_RECURSE src_cpp src/*.cpp) file(GLOB_RECURSE src_cu src/*.cu ) file(GLOB_RECURSE src_h src/*.h ) add_library(cobjs STATIC ${src_c} ${src_h} ) add_library(cppobjs STATIC ${src_cpp} ${src_h}) add_library(cuobjs STATIC ${src_cu} ${src_h} ) target_compile_options(cobjs PUBLIC ${CMAKE_C_FLAGS} ) target_compile_options(cppobjs PUBLIC ${CMAKE_CXX_FLAGS}) target_compile_options(cuobjs PUBLIC ${CMAKE_NVCC_FLAGS}) set_target_properties( cuobjs PROPERTIES CUDA_SEPARABLE_COMPILATION ON) add_executable(my_target ${cobjs} ${cppobjs} ${cuobjs} ${src_h} ) # Include Dirs target_include_directories(cobjs PUBLIC include src ) target_include_directories(cppobjs PUBLIC include src ) target_include_directories(cuobjs PUBLIC include src ) target_include_directories(my_target PUBLIC include src ) link_directories( ${POCO_HOME} ${METIS_HOME} ) target_link_libraries(my_target PUBLIC cobjs cppobjs cuobjs -lPocoFoundation -lPocoUtil -lpthread -lgomp -lmetis ) And the working Makefile:
#=============================================================================== CUDA_PATH := /usr/local/cuda METIS_PATH := ${METIS_HOME} POCO_PATH := ${POCO_HOME} # D-debug R-release COMPILEMD := R EXE := coupled.exe CC := gcc CXX := g++ #=============================================================================== DIR_BIN := bin DIR_SRC := src CCFLAGS := -Iinclude -I$(DIR_SRC) -std=c11 -c -Wall -fopenmp CXXFLAGS := -I$(CUDA_PATH)/include -I$(METIS_PATH)/include -I$(POCO_PATH)/include -Iinclude -I$(DIR_SRC) -std=c++11 -c -Wall -fopenmp NVCCFLAGS := -I$(POCO_PATH)/include -I$(DIR_SRC) -std=c++11 -dc -Werror deprecated-declarations LDFLAGS := -L$(METIS_PATH)/lib -lmetis -L$(POCO_PATH)/lib -lPocoUtil -lPocoFoundation -Llib -ltecio -lpthread -lgomp BASENM := $(basename $(EXE)) SUFFIX := $(suffix $(EXE)) SRC_C := $(shell find $(DIR_SRC) -name *.c) SRC_CPP := $(shell find $(DIR_SRC) -name *.cpp) SRC_CU := $(shell find $(DIR_SRC) -name *.cu) OBJ_C := $(SRC_C:%.c=%.o) OBJ_CPP := $(SRC_CPP:%.cpp=%.o) OBJ_CU := $(SRC_CU:%.cu=%.o) ifeq ($(COMPILEMD), D) CCFLAGS += -D_DEBUG -g CXXFLAGS += -D_DEBUG -g NVCCFLAGS += -D_DEBUG -g -G else ifeq ($(COMPILEMD), R) CCFLAGS += -DNDEBUG -O2 CXXFLAGS += -DNDEBUG -O2 NVCCFLAGS += -DNDEBUG -O2 else $(error error COMPILEMD($(COMPILEMD))) endif CCFLAGS += -DKS_FP_DOUBLE -march=native CXXFLAGS += -DKS_FP_DOUBLE -march=native NVCCFLAGS += -DKS_FP_DOUBLE BASENM := $(BASENM)DP$(COMPILEMD) ifeq ($(SRC_CU), ) LD := $(CXX) else NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(CXX) DEVICE_SM := 50 52 60 61 #70 75 $(foreach SM,$(DEVICE_SM),$(eval NVCCFLAGS += -gencode arch=compute_$(SM),code=sm_$(SM))) $(foreach SM,$(DEVICE_SM),$(eval LDFLAGS += -gencode arch=compute_$(SM),code=sm_$(SM))) LD := $(NVCC) endif OBJ := $(OBJ_C) $(OBJ_CPP) $(OBJ_CU) EXE := $(DIR_BIN)/$(BASENM)$(SUFFIX) #=============================================================================== all: $(EXE) .PHONY: all clean cleanall $(EXE): $(OBJ) @mkdir -p $(DIR_BIN) $(LD) $^ $(LDFLAGS) -o $@ $(OBJ_C): %.o: %.c $(CC) $< $(CCFLAGS) -o $@ $(OBJ_CPP): %.o: %.cpp $(CXX) $< $(CXXFLAGS) -o $@ $(OBJ_CU): %.o: %.cu $(NVCC) $< $(NVCCFLAGS) -o $@ clean: -rm -rf $(OBJ) $(EXE) cleanall: -rm -rf $(OBJ) $(DIR_BIN)/*log $(DIR_BIN)/*.exe $(DIR_BIN)/*.dat I am sorry that I could not provide the project's source code.
I am very new to CMake, and any help will be appreciated!
EDIT
I tried the solutions given by @squareskittles which seems to solve the /bin/sh: 1: Syntax error: ";;" unexpected problem. But I got a new error which says:
c++: fatal error: no input files Yet in the corresponding build.make file the error line writes:
/usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o <path-to-my-cpp>/my.cpp.o -c <path-to-my-cpp>/my.cpp EDIT2
Thanks to @squareskittles's answer, I finally get to understand how CMake works. There are actually more than one incorrect parts in the CMakeLists.txt file:
CMake adds automatically
-cflags to C and C++ compilers so there is no need to add it manually.It is preferred to use
add_compile_options()to add compilation flags thanset(CMAKE_<LANG>_FLAGS ...).link_directoriesshould always go beforeadd_library()andadd_executable(). A modern approach instead is to usefind_library(), see here.I finally gave up to manually write multiple stage compilation as I did in my Makefile, and instead added all source files in
add_executable(). CMake seems to have handled the different cases perfectly.
My final working version:
cmake_minimum_required(VERSION 3.9) project(my_target LANGUAGES CUDA CXX C) # STD if (NOT DEFINED CMAKE_CUDA_STANDARD) set(CMAKE_CUDA_STANDARD 11) set(CMAKE_CUDA_STANDARD_REQUIRED ON) endif() find_package(Poco REQUIRED Foundation Util) # Flags set ( CMAKE_C_STANDARD 11 ) set( CMAKE_CXX_STANDARD 11 ) # Compile Objects file(GLOB_RECURSE src_c src/*.c ) file(GLOB_RECURSE src_cpp src/*.cpp) file(GLOB_RECURSE src_cu src/*.cu ) file(GLOB_RECURSE src_h src/*.h ) # message(STATUS "src_c = ${src_c}" ) # message(STATUS "src_cpp = ${src_cpp}") # message(STATUS "src_cu = ${src_cu}" ) # message(STATUS "src_h = ${src_h}" ) add_definitions(-DKS_FP_DOUBLE) link_directories( ${POCO_HOME} ${METIS_HOME} ) add_executable(my_target ${src_c} ${src_cpp} ${src_cu} ${src_h} ) # Include Dirs target_include_directories(my_target PUBLIC include src ) set_target_properties(my_target PROPERTIES CUDA_SEPARABLE_COMPILATION ON ) target_link_libraries(my_target PUBLIC # cobjs # cppobjs # cuobjs -lPocoFoundation -lPocoUtil -lpthread -lgomp -lmetis )