最近给xmake增加了一个新特性,对于一份工程源码,可以不用编写makefile,也不用编写各种make相关的工程描述文件(例如:xmake.lua,makefile.am, cmakelist.txt等)

xmake就可以直接编译他们,这是如何做到的呢,简单来说下实现原理:

  1. 首先扫描当前目录下,xmake所以支持的所有源代码文件
  2. 分析代码,检测哪些代码拥有main入口函数
  3. 所有没有main入口的代码编译成静态库
  4. 带有main入口的代码,编译成可执行程序,同时链接其他静态库程序

这种代码扫描和智能编译,非常简单,目前xmake还不支持多级目录扫描,只对单级目录的代码进行扫描编译。。

开源代码的移植和编译

虽然这种方式,并不是非常智能,限制也不少,但是对于想临时写些代码进行编译运行,或者临时想交叉编译一些简单的开源库代码

这种方式已经足够使用了,下面看下一个实际的例子:

我下载了一份zlib-1.2.10的源码,想要编译它,只需要进入zlib的源码目录执行:

$ cd zlib-1.2.10
$ xmake

就行了,输出结果如下:

xmake.lua not found, scanning files ..
target(zlib-1.2): static
[+]: ./adler32.c
[+]: ./compress.c
[+]: ./crc32.c
[+]: ./deflate.c
[+]: ./gzclose.c
[+]: ./gzlib.c
[+]: ./gzread.c
[+]: ./gzwrite.c
[+]: ./infback.c
[+]: ./inffast.c
[+]: ./inflate.c
[+]: ./inftrees.c
[+]: ./trees.c
[+]: ./uncompr.c
[+]: ./zutil.c
xmake.lua generated, scan ok!��
checking for the architecture ... x86_64
checking for the Xcode SDK version for macosx ... 10.12
checking for the target minimal version ... 10.12
checking for the c compiler (cc) ... xcrun -sdk macosx clang
checking for the c++ compiler (cxx) ... xcrun -sdk macosx clang
checking for the objc compiler (mm) ... xcrun -sdk macosx clang
checking for the objc++ compiler (mxx) ... xcrun -sdk macosx clang++
checking for the swift compiler (sc) ... xcrun -sdk macosx swiftc
checking for the assember (as) ... xcrun -sdk macosx clang
checking for the linker (ld) ... xcrun -sdk macosx clang++
checking for the static library archiver (ar) ... xcrun -sdk macosx ar
checking for the static library extractor (ex) ... xcrun -sdk macosx ar
checking for the shared library linker (sh) ... xcrun -sdk macosx clang++
checking for the debugger (dd) ... xcrun -sdk macosx lldb
checking for the golang compiler (go) ... go
configure
{
ex = "xcrun -sdk macosx ar"
, sh = "xcrun -sdk macosx clang++"
, host = "macosx"
, ar = "xcrun -sdk macosx ar"
, buildir = "build"
, as = "xcrun -sdk macosx clang"
, plat = "macosx"
, xcode_dir = "/Applications/Xcode.app"
, arch = "x86_64"
, mxx = "xcrun -sdk macosx clang++"
, go = "go"
, target_minver = "10.12"
, ccache = "ccache"
, mode = "release"
, clean = true
, cxx = "xcrun -sdk macosx clang"
, cc = "xcrun -sdk macosx clang"
, dd = "xcrun -sdk macosx lldb"
, kind = "static"
, ld = "xcrun -sdk macosx clang++"
, xcode_sdkver = "10.12"
, sc = "xcrun -sdk macosx swiftc"
, mm = "xcrun -sdk macosx clang"
}
configure ok!
clean ok!
[00%]: ccache compiling.release ./adler32.c
[06%]: ccache compiling.release ./compress.c
[13%]: ccache compiling.release ./crc32.c
[20%]: ccache compiling.release ./deflate.c
[26%]: ccache compiling.release ./gzclose.c
[33%]: ccache compiling.release ./gzlib.c
[40%]: ccache compiling.release ./gzread.c
[46%]: ccache compiling.release ./gzwrite.c
[53%]: ccache compiling.release ./infback.c
[60%]: ccache compiling.release ./inffast.c
[66%]: ccache compiling.release ./inflate.c
[73%]: ccache compiling.release ./inftrees.c
[80%]: ccache compiling.release ./trees.c
[86%]: ccache compiling.release ./uncompr.c
[93%]: ccache compiling.release ./zutil.c
[100%]: archiving.release libzlib-1.2.a
build ok!��

通过输出结果,可以看到,xmake会去检测扫描当前目录下的所有.c代码,发现没有main入口,应该是静态库程序,因此执行xmake后,就直接编译成静态库libzlib-1.2.a了

连xmake.lua都没有编写,其实xmake在扫描完成后,会去自动在当前目录下生成一份xmake.lua,下次编译就不需要重新扫描检测了。

自动生成的xmake.lua内容如下:

-- define target
target("zlib-1.2") -- set kind
set_kind("static") -- add files
add_files("./adler32.c")
add_files("./compress.c")
add_files("./crc32.c")
add_files("./deflate.c")
add_files("./gzclose.c")
add_files("./gzlib.c")
add_files("./gzread.c")
add_files("./gzwrite.c")
add_files("./infback.c")
add_files("./inffast.c")
add_files("./inflate.c")
add_files("./inftrees.c")
add_files("./trees.c")
add_files("./uncompr.c")
add_files("./zutil.c")

也许你会说,像这种开源库,直接configure; make不就好了吗,他们自己也有提供makefile来直接编译的,的确是这样,我这里只是举个例子而已。。

当然,很多开源库在交叉编译的时候,通过自带的configure,处理起来还是很繁琐的,用xmake进行交叉编译会更方便些。。

即时地代码编写和编译运行

xmake的这个扫描代码编译特性,主要的目的:还是为了让我们在临时想写些测试代码的时候,不用考虑太多东西,直接上手敲代码,然后快速执行xmake run 来调试验证结果。。

例如:

我想写了个简单的main.c的测试程序,打印hello world!,如果要写makefile或者直接通过gcc命令来,就很繁琐了,你需要:

gcc ./main.c -o demo
./demo

最快速的方式,也需要执行两行命令,而如果用xmake,只需要执行:

xmake run

就行了,它会自动检测到代码后,自动生成对应的xmake.lua,自动编译,自动运行,然后输出:

hello world!

如果你有十几个代码文件,用手敲gcc的方式,或者写makefile的方式,这个差距就更明显了,用xmake还是只需要一行命令:

xmake run

多语言支持

这种代码检测和即时编译,是支持多语言的,不仅支持c/c++,还支持objc/swift,后期还会支持golang(正在开发中)

例如我下载了一份fmdb的ios开源框架代码:

.
├── FMDB.h
├── FMDatabase.h
├── FMDatabase.m
├── FMDatabaseAdditions.h
├── FMDatabaseAdditions.m
├── FMDatabasePool.h
├── FMDatabasePool.m
├── FMDatabaseQueue.h
├── FMDatabaseQueue.m
├── FMResultSet.h
└── FMResultSet.m

想要把它编译成ios的静态库,但是又不想写xmake.lua,或者makefile,那么只需要使用xmake的这个新特性,直接执行:

$ xmake f -p iphoneos; xmake

就行了,输出结果如下:

xmake.lua not found, scanning files ..
target(FMDB): static
[+]: ./FMDatabase.m
[+]: ./FMDatabaseAdditions.m
[+]: ./FMDatabasePool.m
[+]: ./FMDatabaseQueue.m
[+]: ./FMResultSet.m
xmake.lua generated, scan ok!��
checking for the architecture ... armv7
checking for the Xcode SDK version for iphoneos ... 10.1
checking for the target minimal version ... 10.1
checking for the c compiler (cc) ... xcrun -sdk iphoneos clang
checking for the c++ compiler (cxx) ... xcrun -sdk iphoneos clang
checking for the objc compiler (mm) ... xcrun -sdk iphoneos clang
checking for the objc++ compiler (mxx) ... xcrun -sdk iphoneos clang++
checking for the assember (as) ... gas-preprocessor.pl xcrun -sdk iphoneos clang
checking for the linker (ld) ... xcrun -sdk iphoneos clang++
checking for the static library archiver (ar) ... xcrun -sdk iphoneos ar
checking for the static library extractor (ex) ... xcrun -sdk iphoneos ar
checking for the shared library linker (sh) ... xcrun -sdk iphoneos clang++
checking for the swift compiler (sc) ... xcrun -sdk iphoneos swiftc
configure
{
ex = "xcrun -sdk iphoneos ar"
, ccache = "ccache"
, host = "macosx"
, ar = "xcrun -sdk iphoneos ar"
, buildir = "build"
, as = "/usr/local/share/xmake/tools/utils/gas-preprocessor.pl xcrun -sdk iphoneos clang"
, arch = "armv7"
, mxx = "xcrun -sdk iphoneos clang++"
, cxx = "xcrun -sdk iphoneos clang"
, target_minver = "10.1"
, xcode_dir = "/Applications/Xcode.app"
, clean = true
, sh = "xcrun -sdk iphoneos clang++"
, cc = "xcrun -sdk iphoneos clang"
, ld = "xcrun -sdk iphoneos clang++"
, mode = "release"
, kind = "static"
, plat = "iphoneos"
, xcode_sdkver = "10.1"
, sc = "xcrun -sdk iphoneos swiftc"
, mm = "xcrun -sdk iphoneos clang"
}
configure ok!
clean ok!
[00%]: ccache compiling.release ./FMDatabase.m
[20%]: ccache compiling.release ./FMDatabaseAdditions.m
[40%]: ccache compiling.release ./FMDatabasePool.m
[60%]: ccache compiling.release ./FMDatabaseQueue.m
[80%]: ccache compiling.release ./FMResultSet.m
[100%]: archiving.release libFMDB.a
build ok!��

同时编译多个可执行文件

输出结果的开头部分,就是对代码的分析结果,虽然目前只支持单级目录结构的代码扫描,但是还是可以同时支持检测和编译多个可执行文件的

我们以libjpeg的开源库为例:

我们进入jpeg-6b目录后,执行:

$ xmake

输出如下:

xmake.lua not found, scanning files ..
target(jpeg-6b): static
[+]: ./cdjpeg.c
[+]: ./example.c
[+]: ./jcapimin.c
[+]: ./jcapistd.c
[+]: ./jccoefct.c
[+]: ./jccolor.c
[+]: ./jcdctmgr.c
[+]: ./jchuff.c
[+]: ./jcinit.c
[+]: ./jcmainct.c
[+]: ./jcmarker.c
[+]: ./jcmaster.c
[+]: ./jcomapi.c
[+]: ./jcparam.c
[+]: ./jcphuff.c
[+]: ./jcprepct.c
[+]: ./jcsample.c
[+]: ./jctrans.c
[+]: ./jdapimin.c
[+]: ./jdapistd.c
[+]: ./jdatadst.c
[+]: ./jdatasrc.c
[+]: ./jdcoefct.c
[+]: ./jdcolor.c
[+]: ./jddctmgr.c
[+]: ./jdhuff.c
[+]: ./jdinput.c
[+]: ./jdmainct.c
[+]: ./jdmarker.c
[+]: ./jdmaster.c
[+]: ./jdmerge.c
[+]: ./jdphuff.c
[+]: ./jdpostct.c
[+]: ./jdsample.c
[+]: ./jdtrans.c
[+]: ./jerror.c
[+]: ./jfdctflt.c
[+]: ./jfdctfst.c
[+]: ./jfdctint.c
[+]: ./jidctflt.c
[+]: ./jidctfst.c
[+]: ./jidctint.c
[+]: ./jidctred.c
[+]: ./jmemansi.c
[+]: ./jmemmgr.c
[+]: ./jmemname.c
[+]: ./jmemnobs.c
[+]: ./jquant1.c
[+]: ./jquant2.c
[+]: ./jutils.c
[+]: ./rdbmp.c
[+]: ./rdcolmap.c
[+]: ./rdgif.c
[+]: ./rdppm.c
[+]: ./rdrle.c
[+]: ./rdswitch.c
[+]: ./rdtarga.c
[+]: ./transupp.c
[+]: ./wrbmp.c
[+]: ./wrgif.c
[+]: ./wrppm.c
[+]: ./wrrle.c
[+]: ./wrtarga.c
target(ansi2knr): binary
[+]: ./ansi2knr.c
target(cjpeg): binary
[+]: ./cjpeg.c
target(ckconfig): binary
[+]: ./ckconfig.c
target(djpeg): binary
[+]: ./djpeg.c
target(jpegtran): binary
[+]: ./jpegtran.c
target(rdjpgcom): binary
[+]: ./rdjpgcom.c
target(wrjpgcom): binary
[+]: ./wrjpgcom.c
xmake.lua generated, scan ok!��
checking for the architecture ... x86_64
checking for the Xcode SDK version for macosx ... 10.12
checking for the target minimal version ... 10.12
checking for the c compiler (cc) ... xcrun -sdk macosx clang
checking for the c++ compiler (cxx) ... xcrun -sdk macosx clang
checking for the objc compiler (mm) ... xcrun -sdk macosx clang
checking for the objc++ compiler (mxx) ... xcrun -sdk macosx clang++
checking for the swift compiler (sc) ... xcrun -sdk macosx swiftc
checking for the assember (as) ... xcrun -sdk macosx clang
checking for the linker (ld) ... xcrun -sdk macosx clang++
checking for the static library archiver (ar) ... xcrun -sdk macosx ar
checking for the static library extractor (ex) ... xcrun -sdk macosx ar
checking for the shared library linker (sh) ... xcrun -sdk macosx clang++
checking for the debugger (dd) ... xcrun -sdk macosx lldb
checking for the golang compiler (go) ... go
configure
{
ex = "xcrun -sdk macosx ar"
, sh = "xcrun -sdk macosx clang++"
, host = "macosx"
, ar = "xcrun -sdk macosx ar"
, buildir = "build"
, as = "xcrun -sdk macosx clang"
, plat = "macosx"
, xcode_dir = "/Applications/Xcode.app"
, arch = "x86_64"
, mxx = "xcrun -sdk macosx clang++"
, go = "go"
, target_minver = "10.12"
, ccache = "ccache"
, mode = "release"
, clean = true
, cxx = "xcrun -sdk macosx clang"
, cc = "xcrun -sdk macosx clang"
, dd = "xcrun -sdk macosx lldb"
, kind = "static"
, ld = "xcrun -sdk macosx clang++"
, xcode_sdkver = "10.12"
, sc = "xcrun -sdk macosx swiftc"
, mm = "xcrun -sdk macosx clang"
}
configure ok!
clean ok!
[00%]: ccache compiling.release ./cdjpeg.c
[00%]: ccache compiling.release ./example.c
[00%]: ccache compiling.release ./jcapimin.c
[00%]: ccache compiling.release ./jcapistd.c
[00%]: ccache compiling.release ./jccoefct.c
[00%]: ccache compiling.release ./jccolor.c
[01%]: ccache compiling.release ./jcdctmgr.c
[01%]: ccache compiling.release ./jchuff.c
[01%]: ccache compiling.release ./jcinit.c
[01%]: ccache compiling.release ./jcmainct.c
[01%]: ccache compiling.release ./jcmarker.c
[02%]: ccache compiling.release ./jcmaster.c
[02%]: ccache compiling.release ./jcomapi.c
[02%]: ccache compiling.release ./jcparam.c
[02%]: ccache compiling.release ./jcphuff.c
[02%]: ccache compiling.release ./jcprepct.c
[03%]: ccache compiling.release ./jcsample.c
[03%]: ccache compiling.release ./jctrans.c
[03%]: ccache compiling.release ./jdapimin.c
[03%]: ccache compiling.release ./jdapistd.c
[03%]: ccache compiling.release ./jdatadst.c
[04%]: ccache compiling.release ./jdatasrc.c
[04%]: ccache compiling.release ./jdcoefct.c
[04%]: ccache compiling.release ./jdcolor.c
[04%]: ccache compiling.release ./jddctmgr.c
[04%]: ccache compiling.release ./jdhuff.c
[05%]: ccache compiling.release ./jdinput.c
[05%]: ccache compiling.release ./jdmainct.c
[05%]: ccache compiling.release ./jdmarker.c
[05%]: ccache compiling.release ./jdmaster.c
[05%]: ccache compiling.release ./jdmerge.c
[06%]: ccache compiling.release ./jdphuff.c
[06%]: ccache compiling.release ./jdpostct.c
[06%]: ccache compiling.release ./jdsample.c
[06%]: ccache compiling.release ./jdtrans.c
[06%]: ccache compiling.release ./jerror.c
[07%]: ccache compiling.release ./jfdctflt.c
[07%]: ccache compiling.release ./jfdctfst.c
[07%]: ccache compiling.release ./jfdctint.c
[07%]: ccache compiling.release ./jidctflt.c
[07%]: ccache compiling.release ./jidctfst.c
[08%]: ccache compiling.release ./jidctint.c
[08%]: ccache compiling.release ./jidctred.c
[08%]: ccache compiling.release ./jmemansi.c
[08%]: ccache compiling.release ./jmemmgr.c
[08%]: ccache compiling.release ./jmemname.c
[09%]: ccache compiling.release ./jmemnobs.c
[09%]: ccache compiling.release ./jquant1.c
[09%]: ccache compiling.release ./jquant2.c
[09%]: ccache compiling.release ./jutils.c
[09%]: ccache compiling.release ./rdbmp.c
[10%]: ccache compiling.release ./rdcolmap.c
[10%]: ccache compiling.release ./rdgif.c
[10%]: ccache compiling.release ./rdppm.c
[10%]: ccache compiling.release ./rdrle.c
[10%]: ccache compiling.release ./rdswitch.c
[11%]: ccache compiling.release ./rdtarga.c
[11%]: ccache compiling.release ./transupp.c
[11%]: ccache compiling.release ./wrbmp.c
[11%]: ccache compiling.release ./wrgif.c
[11%]: ccache compiling.release ./wrppm.c
[12%]: ccache compiling.release ./wrrle.c
[12%]: ccache compiling.release ./wrtarga.c
[12%]: archiving.release libjpeg-6b.a
[12%]: ccache compiling.release ./wrjpgcom.c
[25%]: linking.release wrjpgcom
[25%]: ccache compiling.release ./ansi2knr.c
[37%]: linking.release ansi2knr
[37%]: ccache compiling.release ./jpegtran.c
[50%]: linking.release jpegtran
[50%]: ccache compiling.release ./djpeg.c
[62%]: linking.release djpeg
[62%]: ccache compiling.release ./ckconfig.c
[75%]: linking.release ckconfig
[75%]: ccache compiling.release ./rdjpgcom.c
[87%]: linking.release rdjpgcom
[87%]: ccache compiling.release ./cjpeg.c
[100%]: linking.release cjpeg
build ok!��

可以看到,处理静态库,xmake还分析出了很多可执行的测试程序,剩下的代码统一编译成一个 libjpeg.a 的静态库,供哪些测试程序链接使用。。

target(ansi2knr): binary
[+]: ./ansi2knr.c
target(cjpeg): binary
[+]: ./cjpeg.c
target(ckconfig): binary
[+]: ./ckconfig.c
target(djpeg): binary
[+]: ./djpeg.c
target(jpegtran): binary
[+]: ./jpegtran.c
target(rdjpgcom): binary
[+]: ./rdjpgcom.c
target(wrjpgcom): binary
[+]: ./wrjpgcom.c

遇到的一些问题和限制

当前xmake的这种自动分析检测还不是非常智能,对于:

  1. 需要特殊的编译选项
  2. 需要依赖其他目录的头文件搜索
  3. 需要分条件编译不同源文件
  4. 同目录需要生成多个静态库
  5. 需要多级目录支持的源码库

以上这些情况,xmake暂时还没发自动化的智能处理,其中限制1,2还是可以解决的,通过半手动的方式,例如:

$ xmake f --cxflags="" --ldflags="" --includedirs="" --linkdirs=""; xmake

在自动检测编译的时候,手动配置这个源码工程需要的特殊编译选项,就可以直接通过编译了

而限制3,暂时只能通过删源代码来解决了,就像刚才编译jpeg的代码,其实它的目录下面同时存在了:

jmemdos.c
jmemmac.c
jmemansi.c

其中两个是没法编译过的,需要删掉后才行。。


个人主页:TBOOX开源工程

xmake新增智能代码扫描编译模式的更多相关文章

  1. xmake新增对WDK驱动编译环境支持

    xmake v2.2.1新版本现已支持WDK驱动编译环境,我们可以直接在系统原生cmd终端下,执行xmake进行驱动编译,甚至配合vscode, sublime text, IDEA等编辑器+xmak ...

  2. xmake新增对Cuda代码编译支持

    最近研究了下NVIDIA Cuda Toolkit的编译环境,并且在xmake 2.1.10开发版中,新增了对cuda编译环境的支持,可以直接编译*.cu代码. 关于Cuda Toolkit相关说明以 ...

  3. xmake从入门到精通8:切换编译模式

    xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验. 本文我们会详细介绍下如何在项目构建过程中切换deb ...

  4. Release编译模式下,事件是否会引起内存泄漏问题初步研究

    题记:不常发生的事件内存泄漏现象 想必有些朋友也常常使用事件,但是很少解除事件挂钩,程序也没有听说过内存泄漏之类的问题.幸运的是,在某些情况下,的确不会出问题,很多年前做的项目就跑得好好的,包括我也是 ...

  5. Snippet Compiler——代码段编译工具

    原文地址:http://www.cnblogs.com/conexpress/archive/2011/07/24/2115308.html 不知道大家在工作中是否遇到过下面的情况:在项目中实现了一段 ...

  6. PHP微信支付开发之扫描支付(模式二)后如何回调

    其实在写这篇文章的时候感觉自己已经落伍了,不过笔者在百度上搜索"微信支付开发之扫描支付(模式二)后如何回调"寻找答案时,发现依旧有很多朋友没有解决这个问题,所以就把自己的解决思路分 ...

  7. 静态代码扫描工具PMD定制xml的规则(一)操作篇

    0.前言 PMD作为开源的静态代码扫描工具有很强的扩展能力,可使用java或xpath定制rule.第一篇从操作上讲解如何定制一个用于扫描xml是否规范的规则.首先我们知道xml格式的文件在java工 ...

  8. Apollo 代码的编译演示

    Apollo 代码的编译演示 官方的文档 -- 运行线下演示 如果你没有车辆及车载硬件, Apollo还提供了一个计算机模拟环境,可用于演示和代码调试. 线下演示需要设置docker的release环 ...

  9. 使用OClint进行iOS项目的静态代码扫描

    使用OClint进行iOS项目的静态代码扫描 原文链接:http://blog.yourtion.com/static-code-analysis-ios-using-oclint.html 最近需要 ...

随机推荐

  1. vue简单插件

    已经很久没有学习新的相关知识,对于今后的学习方向可能会集中在vue的源码,render,jsx语法,服务端渲染来学习,巩固好vue的基础和高级的知识,现阶段vue的api和基本用法已经全部掌握,但是还 ...

  2. 磁盘,fdisk分区,MBR,dd命令

    光盘和磁盘.u盘.软盘.硬盘有什么区别 ①光盘: cdrom/dvdrom:光驱(光盘驱动器)    rom:只读    ram:可以擦写    cd:700M    dvd:4G ②软盘:flopp ...

  3. php 获取准确的ip,并通过ip准确获取所在区域 的方法

    本人qq群也有许多的技术文档,希望可以为你提供一些帮助(非技术的勿加). QQ群:   281442983 (点击链接加入群:http://jq.qq.com/?_wv=1027&k=29Lo ...

  4. VS插件CodeRush for Visual Studio发布v18.2.9|附下载

    CodeRush能帮助你以极高的效率创建和维护源代码.Consume-first 申明,强大的模板,智能的选择工具,智能代码分析和创新的导航以及一个无与伦比的重构集,在它们的帮助下能够大大的提高你效率 ...

  5. NOIP2016 D1T1 玩具谜题

    洛谷P1563 看完了noip2017觉得noip2016是真的简单……2017第一题就卡住2016第一题10分钟AC 思路: m<=100000很明显暴力模拟就可以 唯一有一点点难度的地方就是 ...

  6. 【leetcode】1131. Maximum of Absolute Value Expression

    题目如下: Given two arrays of integers with equal lengths, return the maximum value of: |arr1[i] - arr1[ ...

  7. Java各种锁机制简述

    线程安全是多线程领域的问题,线程安全可以简单理解为一个方法或者一个实例可以在多线程环境中使用而不会出现问题. 在 Java 多线程编程当中,提供了多种实现 Java 线程安全的方式: 最简单的方式,使 ...

  8. css-外面元素的高度,由里面的元素进行撑开(由内部的高度决定)

    1.删除你的高度的固定值 2.将父元素的====>display:inline-block; 或者设置浮动====>float:left;

  9. 使用HTML和CSS来实现为文字设置图片底纹

    先看一下最终实现的效果 图中的hello是文本而不是图片 那么如何实现这种效果呢? HTML部分: 创建一个h1标签 ,标签内容为(hello).通过link标签链接外部样式表style.css. s ...

  10. HTML中的marquee标签实现滚动效果

    一.标签<marquee>简介 通过开始标签<marquee>和结束标签</marquee>的共同配合而实现滚动效果,<marquee>滚动的内容< ...