在makefile中只能使用一个对象文件进行制作吗

时间:2022-05-14 15:00:07

So I am trying to make my own make file for cross compiling code. I am getting the C files out of a folder with a wildcard but when I have more than one C files in the csources folder it will not create the object files.

所以我正在尝试为交叉编译代码制作我自己的make文件。我正在用通配符从一个文件夹中取出C文件,但是当csources文件夹中有多个C文件时,它将不会创建对象文件。

# Macros
linux_compiler = gcc
win32_compiler = i686-w64-mingw32-gcc
win64_compiler = x86_64-w64-mingw32-gcc
program = main

cfolder = csources
headerfolder = hsources
objectfolder = osources

csources = $(wildcard $(cfolder)/*.c)
hsources = $(wildcard $(headerfolder)/*.h)

osources_linux = $(patsubst $(cfolder)/%.c,$(objectfolder)/%_linux.o,$(wildcard $(cfolder)/*.c))
osources_win32 = $(patsubst $(cfolder)/%.c,$(objectfolder)/%_win32.o,$(wildcard $(cfolder)/*.c))
osources_win64 = $(patsubst $(cfolder)/%.c,$(objectfolder)/%_win64.o,$(wildcard $(cfolder)/*.c))

# First target
all: clearscreen $(program)_win64 $(program)_win32 $(program)_linux
    $(info $(program) created $(csources))

# Use to force compile the program
force: clean clearscreen $(program)_win64 $(program)_win32 $(program)_linux
    $(info $(program) forcible created)

$(program)_linux: $(osources_linux) $(objectfolder)/$(program)_linux.o
    $(linux_compiler) $(objectfolder)/$(program)_linux.o $(osources_linux) -o $(program)_linux

$(program)_win32: $(osources_win32) $(objectfolder)/$(program)_win32.o
    $(win32_compiler) $(objectfolder)/$(program)_win32.o $(osources_win32) -o $(program)_win32

$(program)_win64: $(osources_win64) $(objectfolder)/$(program)_win64.o
    $(win64_compiler) $(objectfolder)/$(program)_win64.o $(osources_win64) -o $(program)_win64

$(osources_linux): $(csources) $(hsources) 
    $(linux_compiler) -c $(csources) -o $(osources_linux) 

$(osources_win32): $(csources) $(hsources) 
    $(win32_compiler) -c $(csources) -o $(osources_win32) 

$(osources_win64): $(csources) $(hsources) 
    $(win64_compiler) -c $(csources) -o $(osources_win64)  

$(objectfolder)/$(program)_linux.o: $(program).c
    $(linux_compiler) -c $(program).c -o $(objectfolder)/$(program)_linux.o

$(objectfolder)/$(program)_win32.o: $(program).c
    $(win32_compiler) -c $(program).c -o $(objectfolder)/$(program)_win32.o

$(objectfolder)/$(program)_win64.o: $(program).c
    $(win64_compiler) -c $(program).c -o $(objectfolder)/$(program)_win64.o

clearscreen:
    clear

clean:
    rm $(objectfolder)/*.o

I don't know that much about makefiles, I thought this should work, but it's not making any object files.

我不太了解makefile,我认为它应该可以工作,但是它不会生成任何对象文件。

$(osources_win64): $(csources) $(hsources)      
     $(win64_compiler) -c $(csources) -o $(osources_win64)

And the error I got when I do have more then one c file in the cfolder:

当我在cfolder中有一个c文件时,我得到的错误是

x86_64-w64-mingw32-gcc -c csources/log.c csources/SDL_add.c -o osources/log_win64.o osources/SDL_add_win64.o  
x86_64-w64-mingw32-gcc: error: osources/SDL_add_win64.o: No such file or directory
makefile:132: recipe for target 'osources/SDL_add_win64.o' failed
make: *** [osources/SDL_add_win64.o] Error 1

Solution:

解决方案:

###############################################################################
## This is the makefile for the application within the SDL2 (game) engine    ##
## This will crosscompile your code to linux and windows (32 and 64 bit)     ##
## Started development in 19-02-2016                                         ##
## Version = 1.00                                                            ##
## Status  = Operational                                                     ##     
## Author  = Marijn van Tricht                                               ##
##                                                                           ##
## === Log ================================================================= ##
##                                                                           ##
## 20-02-2016 - Version 1.00 created                                         ##
##                                                                           ##
###############################################################################

###############################################################################
## Read below to understand the makefile                                     ##
###############################################################################
##                                                                           ##
## === Functions =========================================================== ##
##                                                                           ##
## generic format of a target                                                ##            
## Target: Dependencies                                                      ##
## <TAB> Command                                                             ##
##                                                                           ##
## Target:                                                                   ##
## Target is a function, when make is called it will automaticly select the  ##
## first target.                                                             ##
##                                                                           ##
## Dependencies:                                                             ##
## Here there's a list of files or function needed to execute the command.   ##
## When a depencie is a function it will execute that function before it     ##
## will make the target.                                                     ##
##                                                                           ##
## Command:                                                                  ##
## Here the information is provided which will be pasted in the terminal.    ##
##                                                                           ##
## === Compiling =========================================================== ##
##                                                                           ##
## One of those commands could be to compile your code. general thats what a ##
## makefile is made to do.                                                   ##
##                                                                           ##
## In the simplest form the command to compile a program is a compiler like  ## 
## gcc or g++ and a c or cpp file as an argument.                            ##
## For example:                                                              ##
## gcc main.c                                                                ##
##                                                                           ##
## this will generate a program called a.out                                 ##
##                                                                           ##
## === Parameters ========================================================== ##
##                                                                           ##
## With this command you can give a lot of parameters.                       ##
## For example -o main will change the output filename to main.out so,       ##
## gcc main.c -o main will result in a file called main.out                  ##
##                                                                           ##
## All the parameters used by this makefile are described and listed below.  ##
##                                                                           ##
##  -o <filename>   | This will change the output name of function to be     ## 
##                  | filename                                               ##
##                                                                           ##
##  -c              | This will compile to the program to objectfiles. This  ##
##                  | can than later be compiled again with the compiler to  ##
##                  | a program. The change is that the objectfiles won't be ##
##                  | deleted by the compiler.                               ##
##                                                                           ##
## === Macros ============================================================== ##
##                                                                           ##
## Macros can copy paste lines in your code for example you could make a     ##
## macro for the compiler you'll use. You can do that by adding the          ## 
## following:                                                                ##
## Compiler = gcc                                                            ##
##                                                                           ##
## This can then be pasted into the code by using $(compiler).               ##
## So Macros can be defined be the = sign and can be pasted by $(macro).     ##
##                                                                           ##
## === Specific functions ================================================== ##
##                                                                           ## 
## There are a few Specific functions you can use in a makefile those are    ##
## used in the sameway as macros do a list of specific functions that are    ##
## used in this makefile are listed below.                                   ##
##                                                                           ##
##  $(info <text>)                         | The <text> will be printed in   ## 
##                                         | the terminal                    ##
##                                                                           ##
##  $(wildcard <folder>/*.<format>         | This will select all the        ##
##                                         | .<format> files in the selected ##
##                                         | <folder>                        ##
##                                                                           ##
##  $(patsubst <replace>,<with>,<file(s)>) | With this we can replace the    ##
##                                         | name(s) of some file(s)         ##
##                                                                           ##
###############################################################################

# Macros
linux_compiler = gcc
win32_compiler = i686-w64-mingw32-gcc
win64_compiler = x86_64-w64-mingw32-gcc

linux_flags = -lSDL2
win32_flags = -lSDL2main -lSDL2
win64_flags = -lSDL2main -lSDL2

program = main

cfolder = csources/
headerfolder = hsources/
objectfolder = osources/

csources = $(wildcard $(cfolder)*.c)
hsources = $(wildcard $(headerfolder)*.h)

osources_linux = $(patsubst $(cfolder)%.c,$(objectfolder)%_linux.o,$(wildcard $(cfolder)*.c))
osources_win32 = $(patsubst $(cfolder)%.c,$(objectfolder)%_win32.o,$(wildcard $(cfolder)*.c))
osources_win64 = $(patsubst $(cfolder)%.c,$(objectfolder)%_win64.o,$(wildcard $(cfolder)*.c))

# First target
all: clearscreen $(objectfolder) $(program)_win64 $(program)_win32 $(program)_linux
    $(info $(program) created)

# Use to force compile the program
force: clean clearscreen $(objectfolder) $(program)_win64 $(program)_win32 $(program)_linux
    $(info $(program) forcible created)

$(program)_linux: $(osources_linux) $(objectfolder)$(program)_linux.o
    $(linux_compiler) $(linux_flags) $(objectfolder)$(program)_linux.o $(osources_linux) -o $(program)_linux

$(program)_win32: $(osources_win32) $(objectfolder)$(program)_win32.o
    $(win32_compiler) $(objectfolder)$(program)_win32.o $(osources_win32) -o $(program)_win32 $(win32_flags)

$(program)_win64: $(osources_win64) $(objectfolder)$(program)_win64.o
    $(win64_compiler) $(objectfolder)$(program)_win64.o $(osources_win64) -o $(program)_win64 $(win64_flags)

$(objectfolder)%_linux.o: $(cfolder)%.c
    $(linux_compiler) -c $? -D LINUX -o $@

$(objectfolder)%_win32.o: $(cfolder)%.c
    $(win32_compiler) -c $? -D WIN32 -o $@

$(objectfolder)%_win64.o: $(cfolder)%.c
    $(win64_compiler) -c $? -D WIN64 -o $@

$(objectfolder)$(program)_linux.o: $(program).c
    $(linux_compiler) -c $(program).c -D LINUX -o $(objectfolder)$(program)_linux.o 

$(objectfolder)$(program)_win32.o: $(program).c
    $(win32_compiler) -c $(program).c -D WIN32 -o $(objectfolder)$(program)_win32.o

$(objectfolder)$(program)_win64.o: $(program).c
    $(win64_compiler) -c $(program).c -D WIN64 -o $(objectfolder)$(program)_win64.o

$(objectfolder):
    mkdir $(objectfolder)

clearscreen:
    clear

clean:
    rm $(objectfolder)*.o

2 个解决方案

#1


1  

You need some generic rules to make object files in each platform.

您需要一些通用规则来在每个平台中创建对象文件。

$(objectfolder)/%_linux.o: $(cfolder)/%.c
    $(linux_compiler) -c $? -o $@

$(objectfolder)/%_win32.o: $(cfolder)/%.c
    $(win32_compiler) -c $? -o $@

$(objectfolder)/%_win64.o: $(cfolder)/%.c
    $(win64_compiler) -c $? -o $@

#2


1  

Look at this example:

看看这个例子:

sakkath ~ $ gcc -c file1.c file2.c -o file1.o file2.o
gcc: error: file2.o: No such file or directory
sakkath ~ $

You cannot specify two arguments to -o, and if you try to use the "-o" flag twice, this happens:

不能为-o指定两个参数,如果您尝试两次使用“-o”标志,就会发生以下情况:

gcc: fatal error: cannot specify -o with -c, -S or -E with multiple files
compilation terminated.

The only reason you can specify multiple files when you are NOT using -c, is because the linking stage is invoked, and by definition one executable is produced by linking multiple files together. But this is still only one argument to "-o". The reason you are getting the error you are, is because gcc is interpreting the file you are trying to specify as the second argument to "-o" as an additional input file. Consider this:

当不使用-c时,您可以指定多个文件的唯一原因是,链接阶段被调用,根据定义,一个可执行文件是通过将多个文件链接在一起生成的。但这仍然只是“-o”的一个论点。您获得错误的原因是,gcc将您试图指定的文件作为“-o”的第二个参数作为附加输入文件。考虑一下:

gcc file1.c -o main file2.c

This will not create two output files, but will be exactly the same as if you invoked it this way (the order of arguments doesn't really matter basically):

这将不会创建两个输出文件,但将与您以这种方式调用它的方式完全相同(参数的顺序实际上并不重要):

gcc file1.c file2.c -o main 

#1


1  

You need some generic rules to make object files in each platform.

您需要一些通用规则来在每个平台中创建对象文件。

$(objectfolder)/%_linux.o: $(cfolder)/%.c
    $(linux_compiler) -c $? -o $@

$(objectfolder)/%_win32.o: $(cfolder)/%.c
    $(win32_compiler) -c $? -o $@

$(objectfolder)/%_win64.o: $(cfolder)/%.c
    $(win64_compiler) -c $? -o $@

#2


1  

Look at this example:

看看这个例子:

sakkath ~ $ gcc -c file1.c file2.c -o file1.o file2.o
gcc: error: file2.o: No such file or directory
sakkath ~ $

You cannot specify two arguments to -o, and if you try to use the "-o" flag twice, this happens:

不能为-o指定两个参数,如果您尝试两次使用“-o”标志,就会发生以下情况:

gcc: fatal error: cannot specify -o with -c, -S or -E with multiple files
compilation terminated.

The only reason you can specify multiple files when you are NOT using -c, is because the linking stage is invoked, and by definition one executable is produced by linking multiple files together. But this is still only one argument to "-o". The reason you are getting the error you are, is because gcc is interpreting the file you are trying to specify as the second argument to "-o" as an additional input file. Consider this:

当不使用-c时,您可以指定多个文件的唯一原因是,链接阶段被调用,根据定义,一个可执行文件是通过将多个文件链接在一起生成的。但这仍然只是“-o”的一个论点。您获得错误的原因是,gcc将您试图指定的文件作为“-o”的第二个参数作为附加输入文件。考虑一下:

gcc file1.c -o main file2.c

This will not create two output files, but will be exactly the same as if you invoked it this way (the order of arguments doesn't really matter basically):

这将不会创建两个输出文件,但将与您以这种方式调用它的方式完全相同(参数的顺序实际上并不重要):

gcc file1.c file2.c -o main